/*
Filename            main.c v1.2
Date                2012-11-11
Description         Main file of WaterGate Controller Project
Hardware            MegaWin MPC82G516A
Compiler            Keil PK51 v9.02
Written by          Somchai.RID & Kanthee.FTPS
Organization        Royal Irrigation Department (RID)
*/

#include <reg52.h>
#include <string.h>

#define STOP_DELAY 0x1000

sbit Si     = P3^3;  //P1^0
sbit Latch  = P3^4;  //P1^1
sbit Sclk   = P3^5;  //P1^2

sbit Relay0 = P2^0;
sbit Relay1 = P2^1;
sbit Relay2 = P2^2;
sbit Relay3 = P2^3;
sbit Relay4 = P2^4;
sbit Relay5 = P2^5;
sbit Relay6 = P2^6;
sbit Relay7 = P2^7;
sbit Relay8 = P1^0;
sbit Relay9 = P1^1;
sbit RelayA = P1^2;
sbit RelayB = P1^3;
sbit RelayC = P1^4;
sbit RelayD = P1^5;
sbit RelayE = P1^6;
sbit RelayF = P1^7;

char Command[32+1];
unsigned char CommandLen = 0;
  
void Delay(unsigned int mSec)
{
  unsigned int t;
  while(mSec) {
    t = 115;
    while(t > 0) {
      t--;
    }
    mSec--;
  }
}

void SetBaudrate(unsigned int baudrate)
{
  // Set RS232 baudrate (Speed x1)
  // for Clock 11.0592 MHz
  SCON = 0x52;
  TMOD = 0x20;
  switch(baudrate) {
    case 1200: {
      TH1 = 0xE8;
      break;
    }
    case 2400: {
      TH1 = 0xF4;
      break;
    }
    case 4800: {
      TH1 = 0xFA;
      break;
    }
    case 9600: {
      TH1 = 0xFD;
      break;
    }
    case 19200: {
      TH1 = 0xFD;
      PCON |= 0x80;
      break;
    }
  }
  TR1 = 1;
  ES = 1;
  EA = 1;
}

/*
unsigned char RxCOM(void)
{
  while(!RI);
  RI = 0;
  return SBUF;
}
*/

void TxCOM(unsigned char TxByte)
{
  TI = 0;
  SBUF = TxByte;
  TI = 0;
  while(!TI);
}

void StrToCOM(char *Text)
{
  while(*Text) {
    TxCOM(*Text);
    Text++;
  }
}

unsigned char RxBuffer[16];
unsigned char RxHead = 0;
unsigned char RxTail = 0;
void COMInterrupt(void) interrupt 4
{
  unsigned char Ch;
  if(RI == 1) {
    Ch = SBUF;
    RI = 0;
    RxBuffer[RxHead++] = Ch;
    RxHead &= 0x0F;
    if(RxHead == RxTail) {
      RxTail++;
      RxTail &= 0x0F;
    }
  }
}

unsigned char xdata HEXStr[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
void Prompt(void)
{
  TxCOM(':');
  TxCOM(HEXStr[P1 >> 4]);
  TxCOM(HEXStr[P1 & 0x0F]);
  TxCOM(HEXStr[P2 >> 4]);
  TxCOM(HEXStr[P2 & 0x0F]);
  TxCOM('>');
}

/*
void DTMFChar(void)
{
  TxCOM('#');
  TxCOM(HEXStr[P0 >> 4]);
  TxCOM(HEXStr[P0 & 0x0F]);
  TxCOM('>');
}
*/

unsigned long GateUPCount_A = 0;
unsigned long GateDOWNCount_A = 0;
unsigned long GateUPCount_B = 0;
unsigned long GateDOWNCount_B = 0;
unsigned long GateUPCount_C = 0;
unsigned long GateDOWNCount_C = 0;
unsigned long GateUPCount_D = 0;
unsigned long GateDOWNCount_D = 0;
unsigned long Heartbeat = 0;
void GateSTOP_All(void)
{
  GateUPCount_A = 0;
  GateDOWNCount_A = 0;
  GateUPCount_B = 0;
  GateDOWNCount_B = 0;
  GateUPCount_C = 0;
  GateDOWNCount_C = 0;
  GateUPCount_D = 0;
  GateDOWNCount_D = 0;
  Relay0 = 0;
  Relay4 = 0;
  Relay7 = 0;
  if(CommandLen == 0) {
    StrToCOM("\r\n");
    Prompt();
  }
  Delay(400);
  Relay0 = 1;
  Relay4 = 1;
  Relay7 = 1;
  if(CommandLen == 0) {
    StrToCOM("\r\n");
    Prompt();
  }
}

void GateSTOP_A(void)
{
  GateUPCount_A = 0;
  GateDOWNCount_A = 0;
  Relay0 = 0;
  if(CommandLen == 0) {
    StrToCOM("\r\n");
    Prompt();
  }
  Delay(400);
  Relay0 = 1;
  if(CommandLen == 0) {
    StrToCOM("\r\n");
    Prompt();
  }
}

void GateUP_A(void)
{
  Relay1 = 0;
  Prompt();
  StrToCOM("\r\n");
  Delay(400);
  Relay1 = 1;
}

void GateDOWN_A(void)
{
  Relay2 = 0;
  Prompt();
  StrToCOM("\r\n");
  Delay(400);
  Relay2 = 1;
}

void GateSTOP_B(void)
{
  GateUPCount_B = 0;
  GateDOWNCount_B = 0;
  Relay4 = 0;
  if(CommandLen == 0) {
    StrToCOM("\r\n");
    Prompt();
  }
  Delay(400);
  Relay4 = 1;
  if(CommandLen == 0) {
    StrToCOM("\r\n");
    Prompt();
  }
}

void GateUP_B(void)
{
  Relay5 = 0;
  Prompt();
  StrToCOM("\r\n");
  Delay(400);
  Relay5 = 1;
}

void GateDOWN_B(void)
{
  Relay6 = 0;
  Prompt();
  StrToCOM("\r\n");
  Delay(400);
  Relay6 = 1;
}

void GateSTOP_C(void)
{
  GateUPCount_C = 0;
  GateDOWNCount_C = 0;
  Relay0 = 0;
  if(CommandLen == 0) {
    StrToCOM("\r\n");
    Prompt();
  }
  Delay(400);
  Relay0 = 1;
  if(CommandLen == 0) {
    StrToCOM("\r\n");
    Prompt();
  }
}

void GateUP_C(void)
{
  Relay9 = 0;
  Prompt();
  StrToCOM("\r\n");
  Delay(400);
  Relay9 = 1;
}

void GateDOWN_C(void)
{
  RelayA = 0;
  Prompt();
  StrToCOM("\r\n");
  Delay(400);
  RelayA = 1;
}

void GateSTOP_D(void)
{
  GateUPCount_D = 0;
  GateDOWNCount_D = 0;
  Relay4 = 0;
  if(CommandLen == 0) {
    StrToCOM("\r\n");
    Prompt();
  }
  Delay(400);
  Relay4 = 1;
  if(CommandLen == 0) {
    StrToCOM("\r\n");
    Prompt();
  }
}

void GateUP_D(void)
{
  RelayD = 0;
  Prompt();
  StrToCOM("\r\n");
  Delay(400);
  RelayD = 1;
}

void GateDOWN_D(void)
{
  RelayE = 0;
  Prompt();
  StrToCOM("\r\n");
  Delay(400);
  RelayE = 1;
}

void LEDInit(void)
{
  Si = 0;
  Latch = 0;
  Sclk = 0;
}

void LEDShow(unsigned char Data)
{
  unsigned char j;
  for(j=0; j < 8; j++) {
    Si = Data & 0x80;
    Data = Data << 1;
    Sclk = 1;
    Sclk = 0;
  }
  Latch	= 1;
  Latch	= 0;
}

code unsigned char LEDNum[]   = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
code unsigned char LEDAlpha[] = {
  0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71, 0x3D, 0x76, 0x30, 0x1E,
  0x00, 0x38, 0x00, 0x54, 0x5C, 0x73, 0x67, 0x50, 0x6D, 0x78,
  0x1C, 0x00, 0x00, 0x00, 0x6E, 0x00
};
void LEDStr(unsigned char *Str)
{
  unsigned char Data, i = 0;
  while(Str[i] != 0) {
    if((Str[i] >= '0') && (Str[i] <= '9')) {
      Data = LEDNum[Str[i] & 0x0F];
      if(Str[i+1] == '.') {
        Data |= 0x80;
        i++;
      }
      LEDShow(Data);
    }
    else if((Str[i] >= 'A') && (Str[i] <= 'Z')) {
      Data = LEDAlpha[Str[i] - 'A'];
      if(Str[i+1] == '.') {
        Data |= 0x80;
        i++;
      }
      LEDShow(Data);
    }
    else if((Str[i] >= 'a') && (Str[i] <= 'z')) {
      Data = LEDAlpha[Str[i] - 'a'];
      if(Str[i+1] == '.') {
        Data |= 0x80;
        i++;
      }
      LEDShow(Data);
    }
    else if(Str[i] == ' ') {
      Data = 0x00;
      if(Str[i+1] == '.') {
        Data |= 0x80;
        i++;
      }
      LEDShow(Data);
    }
    i++;
  }
}

void PrintTitle(void)
{
  StrToCOM("\r\n");
  StrToCOM("+=====================================+\r\n");
  StrToCOM("|     WaterGate Controller v1.00      |\r\n");
  StrToCOM("+=====================================+\r\n");
  StrToCOM("| SwitchOn  ;for Set Relay[4..7]      |\r\n");
  StrToCOM("| SwitchOff ;for Clr Relay[4..7]      |\r\n");
  StrToCOM("| GateStop  ;for Set Relay[0]         |\r\n");
  StrToCOM("| GateUp    ;for Set Relay[1]         |\r\n");
  StrToCOM("| GateDown  ;for Set Relay[2]         |\r\n");
  StrToCOM("| Relay#    ;for Read Relay[#] status |\r\n");
  StrToCOM("| Relay#=0  ;for Clr Relay[#]         |\r\n");
  StrToCOM("| Relay#=1  ;for Set Relay[#]         |\r\n");
  StrToCOM("| LED Text  ;Display Text on LED      |\r\n");
  StrToCOM("+-------------------------------------+\r\n");
  StrToCOM("\r\n");
}

unsigned char DTMFBuff[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00};
char DoneStr[] = "...done\r\n";

void main(void) 
{
  unsigned char xdata CMDOpen[5]  = {0x0A, 0x01, 0x02, 0x08, 0x04};
  unsigned char xdata CMDClose[5] = {0x05, 0x08, 0x02, 0x01, 0x08};
  unsigned char xdata CMDStop[5]  = {0x07, 0x03, 0x09, 0x02, 0x04};
  unsigned char xdata RadioCMD[11][5] = {
    {0X0A,0X09,0X04,0X01,0X06},  //=0
    {0X01,0X08,0X05,0X02,0X05},  //=1
    {0X02,0X07,0X06,0X03,0X04},  //=2
    {0X03,0X06,0X07,0X04,0X03},  //=3
    {0X04,0X05,0X08,0X05,0X02},  //=4
    {0X05,0X04,0X09,0X06,0X01},  //=5
    {0X06,0X03,0X0A,0X07,0X0A},  //=6
    {0X07,0X02,0X01,0X08,0X09},  //=7
    {0X08,0X01,0X02,0X09,0X08},  //=8
    {0X09,0X0A,0X03,0X0A,0X07},  //=9
    {0X09,0X0A,0X09,0X0A,0X09}   //=EMERGENCY
	};



  unsigned char P0Now, P0Last = P0;

  unsigned char Ch;
  unsigned char i;
  unsigned char Relay;

  P2 = 0xFF;
	P1 = 0xFF;
  LEDInit();
  Delay(250);
  SetBaudrate(9600);
  PrintTitle();
  GateSTOP_All();

  while(1) {
    P0Now = P0 & 0x0F;
    if(P0Now != P0Last) {
      Delay(10);
      P0Now = P0 & 0x0F;
      //StrToCOM("\r\n");
      //DTMFChar();
      for(i = 0; i < (5 - 1); i++) {
        DTMFBuff[i] = DTMFBuff[i + 1];
      }
      DTMFBuff[i] = P0Now;
      if(strncmp(DTMFBuff, CMDStop, 5) == 0) {
        GateUPCount_A = 0;
        GateDOWNCount_A = 0;
        Relay0 = 0;
        StrToCOM("\r\n");
        Prompt();
        Delay(400);
        Relay0 = 1;
        StrToCOM("\r\n");
        Prompt();
      }
      if(strncmp(DTMFBuff, CMDOpen, 5) == 0) {
        StrToCOM("\r\n");
        if(GateDOWNCount_A > 0) {
          GateSTOP_A();
        }
        if(GateUPCount_A <= 0) {
          GateUP_A();
        }
        GateUPCount_A = STOP_DELAY;
        Prompt();
      }
      if(strncmp(DTMFBuff, CMDClose, 5) == 0) {
        StrToCOM("\r\n");
        if(GateUPCount_A > 0) {
          GateSTOP_A();
        }
        if(GateDOWNCount_A <= 0) {
          GateDOWN_A();
        }
        GateDOWNCount_A = STOP_DELAY;
        Prompt();
      }
			for(i = 0; i <= 11; i++) {
				if(strncmp(DTMFBuff, RadioCMD[i], 5) == 0) {
					break;
				}
			}
  		if(i <= 11) {
        StrToCOM("\r\n");
				switch(i) {
					case 10: {
						GateSTOP_All();
						break;
					}
					case 2: {
						GateUPCount_A = 0;
						GateDOWNCount_A = 0;
						Relay0 = 0;
						Prompt();
						Delay(400);
						Relay0 = 1;
						StrToCOM("\r\n");
						break;
					}
					case 0: {
						if(GateDOWNCount_A > 0) {
							GateSTOP_A();
						}
						if(GateUPCount_A <= 0) {
							GateUP_A();
						}
						GateUPCount_A = STOP_DELAY;
						break;
					}
					case 1: {
						if(GateUPCount_A > 0) {
							GateSTOP_A();
						}
						if(GateDOWNCount_A <= 0) {
							GateDOWN_A();
						}
						GateDOWNCount_A = STOP_DELAY;
						break;
					}
					case 5: {
						GateUPCount_B = 0;
						GateDOWNCount_B = 0;
						Relay4 = 0;
						Prompt();
						Delay(400);
						Relay4 = 1;
						StrToCOM("\r\n");
						break;
					}
					case 3: {
						if(GateDOWNCount_B > 0) {
							GateSTOP_B();
						}
						if(GateUPCount_B <= 0) {
							GateUP_B();
						}
						GateUPCount_B = STOP_DELAY;
						break;
					}
					case 4: {
						if(GateUPCount_B > 0) {
							GateSTOP_B();
						}
						if(GateDOWNCount_B <= 0) {
							GateDOWN_B();
						}
						GateDOWNCount_B = STOP_DELAY;
						break;
					}
					case 6: {
						if(GateDOWNCount_C > 0) {
							GateSTOP_C();
						}
						if(GateUPCount_C <= 0) {
							GateUP_C();
						}
						GateUPCount_C = STOP_DELAY;
						break;
					}
					case 7: {
						if(GateUPCount_C > 0) {
							GateSTOP_C();
						}
						if(GateDOWNCount_C <= 0) {
							GateDOWN_C();
						}
						GateDOWNCount_C = STOP_DELAY;
						break;
					}
					case 8: {
						if(GateDOWNCount_D > 0) {
							GateSTOP_D();
						}
						if(GateUPCount_D <= 0) {
							GateUP_D();
						}
						GateUPCount_D = STOP_DELAY;
						break;
					}
					case 9: {
						if(GateUPCount_D > 0) {
							GateSTOP_D();
						}
						if(GateDOWNCount_D <= 0) {
							GateDOWN_D();
						}
						GateDOWNCount_D = STOP_DELAY;
						break;
					}
				}
        Prompt();
			}
      P0Last = P0Now;
    }

    if(RxTail == RxHead) {
      // Do something for Idle
      if(GateUPCount_A) {
        GateUPCount_A--;
        if(GateUPCount_A == 0) {
          GateSTOP_A();
        }
      }
      if(GateDOWNCount_A) {
        GateDOWNCount_A--;
        if(GateDOWNCount_A == 0) {
          GateSTOP_A();
        }
      }
      if(GateUPCount_B) {
        GateUPCount_B--;
        if(GateUPCount_B == 0) {
          GateSTOP_B();
        }
      }
      if(GateDOWNCount_B) {
        GateDOWNCount_B--;
        if(GateDOWNCount_B == 0) {
          GateSTOP_B();
        }
      }
      if(GateUPCount_C) {
        GateUPCount_C--;
        if(GateUPCount_C == 0) {
          GateSTOP_C();
        }
      }
      if(GateDOWNCount_C) {
        GateDOWNCount_C--;
        if(GateDOWNCount_C == 0) {
          GateSTOP_C();
        }
      }
      if(GateUPCount_D) {
        GateUPCount_D--;
        if(GateUPCount_D == 0) {
          GateSTOP_D();
        }
      }
      if(GateDOWNCount_D) {
        GateDOWNCount_D--;
        if(GateDOWNCount_D == 0) {
          GateSTOP_D();
        }
      }
      if(++Heartbeat >= 0xF0000) {
        GateUPCount_A = 0;
        GateDOWNCount_A = 0;
        GateUPCount_B = 0;
        GateDOWNCount_B = 0;
        GateUPCount_C = 0;
        GateDOWNCount_C = 0;
        GateUPCount_D = 0;
        GateDOWNCount_D = 0;
        Relay0 = 0;
        Relay4 = 0;
        Relay3 = 0;
        StrToCOM("\r\nReset Computer...\r\n");
        Prompt();
        Delay(200);
        Relay3 = 1;
        Delay(200);
        Relay0 = 1;
        Relay4 = 1;
        StrToCOM("\r\n");
        Prompt();
        Heartbeat = 0;
      }
    }
    else {
      Ch = RxBuffer[RxTail++];
      RxTail &= 0x0F;
      if(Ch == 0x0D) {
        StrToCOM("\r\n");
        for(i = 0; i < CommandLen; i++) {
          if((Command[i] >= 'a') && (Command[i] <= 'z')) {
            Command[i] -= 32;
          }
        }
        if((strcmp(Command, "HELP") == 0)||(strcmp(Command, "?") == 0)) {
          PrintTitle();
        }
				/*
        if((strcmp(Command, "SWITCHON") == 0)||(strcmp(Command, "ON") == 0)) {
          StrToCOM("Switch ON");
          P2 &= 0x0F;
          Delay(100);
          GateSTOP();
          StrToCOM(DoneStr);
        }
        if((strcmp(Command, "SWITCHOFF") == 0)||(strcmp(Command, "OFF") == 0)) {
          StrToCOM("Switch OFF");
          GateSTOP();
          Delay(100);
          P2 |= 0xF0;
          StrToCOM(DoneStr);
        }
				*/
        if(strcmp(Command, "GATEUP") == 0) {
          if(GateDOWNCount_A > 0) {
            GateSTOP_A();
          }
          if(GateUPCount_A <= 0) {
            GateUP_A();
          }
          GateUPCount_A = STOP_DELAY;
        }
        if(strcmp(Command, "GATEDOWN") == 0) {
          if(GateUPCount_A > 0) {
            GateSTOP_A();
          }
          if(GateDOWNCount_A <= 0) {
            GateDOWN_A();
          }
          GateDOWNCount_A = STOP_DELAY;
        }
        if(strcmp(Command, "GATESTOP") == 0) {
          GateUPCount_A = 0;
          GateDOWNCount_A = 0;
          Relay0 = 0;
          Prompt();
          Delay(400);
          Relay0 = 1;
          StrToCOM("\r\n");
        }
        if(strcmp(Command, "A_UP") == 0) {
          if(GateDOWNCount_A > 0) {
            GateSTOP_A();
          }
          if(GateUPCount_A <= 0) {
            GateUP_A();
          }
          GateUPCount_A = STOP_DELAY;
        }
        if(strcmp(Command, "A_DOWN") == 0) {
          if(GateUPCount_A > 0) {
            GateSTOP_A();
          }
          if(GateDOWNCount_A <= 0) {
            GateDOWN_A();
          }
          GateDOWNCount_A = STOP_DELAY;
        }
        if(strcmp(Command, "A_STOP") == 0) {
          GateUPCount_A = 0;
          GateDOWNCount_A = 0;
          Relay0 = 0;
          Prompt();
          Delay(400);
          Relay0 = 1;
          StrToCOM("\r\n");
        }
        if(strcmp(Command, "B_UP") == 0) {
          if(GateDOWNCount_B > 0) {
            GateSTOP_B();
          }
          if(GateUPCount_B <= 0) {
            GateUP_B();
          }
          GateUPCount_B = STOP_DELAY;
        }
        if(strcmp(Command, "B_DOWN") == 0) {
          if(GateUPCount_B > 0) {
            GateSTOP_B();
          }
          if(GateDOWNCount_B <= 0) {
            GateDOWN_B();
          }
          GateDOWNCount_B = STOP_DELAY;
        }
        if(strcmp(Command, "B_STOP") == 0) {
          GateUPCount_B = 0;
          GateDOWNCount_B = 0;
          Relay4 = 0;
          Prompt();
          Delay(400);
          Relay4 = 1;
          StrToCOM("\r\n");
        }
        if(strcmp(Command, "C_UP") == 0) {
          if(GateDOWNCount_C > 0) {
            GateSTOP_C();
          }
          if(GateUPCount_C <= 0) {
            GateUP_C();
          }
          GateUPCount_C = STOP_DELAY;
        }
        if(strcmp(Command, "C_DOWN") == 0) {
          if(GateUPCount_C > 0) {
            GateSTOP_C();
          }
          if(GateDOWNCount_C <= 0) {
            GateDOWN_C();
          }
          GateDOWNCount_C = STOP_DELAY;
        }
        if(strcmp(Command, "C_STOP") == 0) {
          GateUPCount_C = 0;
          GateDOWNCount_C = 0;
          Relay0 = 0;
          Prompt();
          Delay(400);
          Relay0 = 1;
          StrToCOM("\r\n");
        }
        if(strcmp(Command, "D_UP") == 0) {
          if(GateDOWNCount_D > 0) {
            GateSTOP_D();
          }
          if(GateUPCount_D <= 0) {
            GateUP_D();
          }
          GateUPCount_D = STOP_DELAY;
        }
        if(strcmp(Command, "D_DOWN") == 0) {
          if(GateUPCount_D > 0) {
            GateSTOP_D();
          }
          if(GateDOWNCount_D <= 0) {
            GateDOWN_D();
          }
          GateDOWNCount_D = STOP_DELAY;
        }
        if(strcmp(Command, "D_STOP") == 0) {
          GateUPCount_D = 0;
          GateDOWNCount_D = 0;
          Relay4 = 0;
          Prompt();
          Delay(400);
          Relay4 = 1;
          StrToCOM("\r\n");
        }
        if((strncmp(Command, "RELAY", 5) == 0) && (CommandLen >= 6)) {
					if((Command[5] >= '0')&&(Command[5] <= '7')) {
						Relay = (Command[5] - '0') & 0x07;
						StrToCOM("Relay");
						TxCOM('0' + Relay);
						StrToCOM(" was ");
						if(CommandLen >= 8) {
							if(Command[7] & 0x01) {
								P2 |= (1 << Relay);
								StrToCOM("SET\r\n");
							}
							else {
								P2 &= (0xFF ^ (1 << Relay));
								StrToCOM("CLR\r\n");
							}
						}
						else {
							if(P2 & (1 << Relay)) {
								StrToCOM("SET\r\n");
							}
							else {
								StrToCOM("CLR\r\n");
							}
						}
				  }
					if(((Command[5] >= '8')&&(Command[5] <= '9')) || ((Command[5] >= 'A')&&(Command[5] <= 'F'))) {
						if((Command[5] >= '8')&&(Command[5] <= '9'))
						  Relay = Command[5] - '8';
						if((Command[5] >= 'A')&&(Command[5] <= 'F'))
						  Relay = (Command[5] - 'A') + 2;
						StrToCOM("Relay");
						TxCOM('0' + Relay);
						StrToCOM(" was ");
						if(CommandLen >= 8) {
							if(Command[7] & 0x01) {
								P1 |= (1 << Relay);
								StrToCOM("SET\r\n");
							}
							else {
								P1 &= (0xFF ^ (1 << Relay));
								StrToCOM("CLR\r\n");
							}
						}
						else {
							if(P1 & (1 << Relay)) {
								StrToCOM("SET\r\n");
							}
							else {
								StrToCOM("CLR\r\n");
							}
						}
				  }
        }
        if((strncmp(Command, "LED", 3) == 0) && (CommandLen >= 5)) {
          LEDStr(Command+4);
        }
        if((strncmp(Command, "ACK", 3) == 0) && (CommandLen >= 0)) {
          Heartbeat = 0;
        }
        Prompt();
        Command[0] = 0;
        CommandLen = 0;
        continue;
      }
      if(Ch == 0x08) {
        if(CommandLen > 0) {
          CommandLen--;
          Command[CommandLen] = 0;
          TxCOM(0x08);
        }
        continue;
      }
      if(CommandLen < 64) {
        Command[CommandLen++] = Ch;
        Command[CommandLen] = 0;
        TxCOM(Ch);
      }
      else {
        TxCOM(0x07);
      }
    }
  }
}